package com.heima.article.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.mapper.ApAuthorMapper;
import com.heima.article.service.ApArticleService;
import com.heima.common.minio.MinIOFileOptions;
import com.heima.common.util.RequestContextUtil;
import com.heima.feign.clients.BehaviorClient;
import com.heima.feign.clients.UserClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.dtos.LoadBehaviorDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.behavior.pojos.CollectionDoc;
import com.heima.model.behavior.pojos.LikeDoc;
import com.heima.model.common.dtos.ResponseResult;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.ObjectUtils;

import java.io.ByteArrayInputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
    @Autowired
    ApArticleMapper apArticleMapper;
    /**
     * day02-文章列表查询
     *  上拉+首页  type=1
     *  下拉      type=2
     * @param dto
     * @param type
     * @return
     */
    @Override
    public ResponseResult loadDataByType(ArticleHomeDto dto, Integer type) {
        // 1 判断时间是否为空，如果为空，设置为当前时间
        if (ObjectUtils.isEmpty(dto.getMaxBehotTime())) {
            dto.setMaxBehotTime(new Date());
        }
        if (ObjectUtils.isEmpty(dto.getMinBehotTime())) {
            dto.setMinBehotTime(new Date());
        }
        // 2 判断频道id是否为空，如果为空设置"__all__"->默认查询推荐
        if (ObjectUtils.isEmpty(dto.getTag())) {
            dto.setTag("__all__");
        }
        List<ApArticle> list= apArticleMapper.loadType(dto,type);
        return ResponseResult.okResult(list);
    }

    /**
     * 文章同步：审核/修改通过->添加/更新文章
     *  注意：如果是新增文章，最后需要返回文章的articleId（雪花自动产生的）
     *          媒体服务需要跟新新增文章的articleId
     *          【WeMedia服务发布文章时，WmNews中的articleId是空的，不要把WmNews的id认为就是文章id】
     * @param dto
     * @return
     */
    @Autowired
    ApAuthorMapper apAuthorMapper;

    @Autowired
    ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    ApArticleContentMapper apArticleContentMapper;
    @Override
    public ResponseResult<Long> saveArticle(ArticleDto dto) throws Exception {
        // WmNews->ArticleDto->Article,ArticleConfig,ArticleContent
        // 【1】文章id为空，新增-》3张表：文章、配置、内容
        // 1 ArticleDto->Article 添加表：ApArticle
        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(dto,apArticle);
        if (dto.getId() == null) {
            // userId->完善数据：author_id,author_name[因为WmNews中没有->dto中没有]
            ApAuthor apAuthor = apAuthorMapper.selectById(dto.getUserId());
            apArticle.setAuthorId(apAuthor.getId());
            apArticle.setAuthorName(apAuthor.getName());
            apArticleMapper.insert(apArticle);
            // 2 ArticleDto->ArticleConfig 添加表：ApArticle_config
            // 新增文章初始状态都是一致的，直接根据id设置默认值
            ApArticleConfig apArticleConfig = new ApArticleConfig();
            apArticleConfig.setIsComment(1);    //1允许评论，0不允许评论
            apArticleConfig.setIsDelete(0);     //0未删除，1已删除
            apArticleConfig.setIsDown(0);       //0已上架，1已下架
            apArticleConfig.setIsForward(1);    //1允许转发，0不允许
            apArticleConfig.setArticleId(apArticle.getId());
            apArticleConfigMapper.insert(apArticleConfig);

            // 3 ArticleDto->ArticleContent 添加表：ApArticle_content
            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setArticleId(apArticle.getId());
            apArticleContent.setContent(dto.getContent());
            apArticleContentMapper.insert(apArticleContent);

            // 生成静态页资源，Article中url
            generateStatic(apArticleContent);
        }
        // 【2】文章id不为空，修改-》2张表：文章、内容
        else {
            // 1 ArticleDto->Article 更新表：ApArticle
            apArticleMapper.updateById(apArticle);
            // 2 ArticleDto->ArticleContent 更新表：ApArticle_content
            LambdaQueryWrapper<ApArticleContent> wrapper = new LambdaQueryWrapper<ApArticleContent>();
            wrapper.eq(ApArticleContent::getArticleId,apArticle.getId());
            ApArticleContent apArticleContent = apArticleContentMapper.selectOne(wrapper);
            apArticleContent.setContent(dto.getContent());
            apArticleContentMapper.updateById(apArticleContent);
            // 更新内容-》更新静态资源
            generateStatic(apArticleContent);
        }
        return ResponseResult.okResult(apArticle.getId());
    }


    @Autowired
    UserClient userClient;
    @Autowired
    BehaviorClient behaviorClient;
    /**
     * 数据回显
     * @param dto
     * @return
     */
    @Autowired
    MongoTemplate mongoTemplate;
    @Override
    public ResponseResult loadBehavior(LoadBehaviorDto dto) {
        //设置默认值
        HashMap<String, Object> result = new HashMap<>();
        result.put("islike",false);
        result.put("isunlike",false);
        result.put("iscollection",false);
        result.put("isfollow",false);
//        result.put("islike",true);
//        result.put("isunlike",true);
//        result.put("iscollection",true);
//        result.put("isfollow",true);
        Integer userId= RequestContextUtil.get("id");
        //是否点赞
        Query queryLike = Query.query(Criteria.where("userId").is(userId).and("articleId").is(dto.getArticleId()));
        long countLike = mongoTemplate.count(queryLike, LikeDoc.class);
        if (countLike > 0) {
            result.put("islike",true);
        } else {
            result.put("islike",false);
        }

        //是否收藏
        Query query = Query.query(Criteria.where("userId").is(userId).and("articleId").is(dto.getArticleId()));
        long count = mongoTemplate.count(query, CollectionDoc.class);
        if (count > 0) {
            result.put("iscollection",true);
        } else {
            result.put("iscollection",false);
        }

        //是否关注
        Boolean follow = userClient.isFollow(userId, dto.getAuthorId());
        result.put("isfollow",follow);


        return ResponseResult.okResult(result);
    }


    /*
     TODO:文章同步，生成静态资源步骤：
        1、引入configration对象，生成模板对象
        2、准备数据模型（整体是个Map）
        3、生成静态资源
        4、获取静态资源对象，存入MinIO，返回url
        5、url设置给Article
     */
    @Autowired
    Configuration configuration;

    @Autowired
    MinIOFileOptions minIOFileOptions;
    public void generateStatic(ApArticleContent apArticleContent) throws Exception {
//        ApArticle  apArticle = getById(apArticleContent.getArticleId());
//        apArticle.setId(apArticleContent.getArticleId());
//         获取模板对象
        Template template = configuration.getTemplate("article.ftl");
        // 准备数据模型
        List<Map> context= JSON.parseArray(apArticleContent.getContent(), Map.class);
        Map<String, Object> map = new HashMap<>();
        map.put("content",context);
//        FileWriter fileWriter = new FileWriter("D:/freemarker/11/static/html/pp.html");
//        template.process(map, fileWriter);
//        // 获取freemarker静态资源对象
        String htemlContent= FreeMarkerTemplateUtils.processTemplateIntoString(template,map);
        // 存入MinIO，并返回url
        ByteArrayInputStream inputStream = new ByteArrayInputStream(htemlContent.getBytes());
        String url = minIOFileOptions.uploadHtmlFile("/html", apArticleContent.getArticleId()+ ".html", inputStream);
        System.out.println("url = " + url);
        // url写入数据库
        ApArticle apArticle = new ApArticle();
        apArticle.setId(apArticleContent.getArticleId());
        apArticle.setStaticUrl(url);
        apArticleMapper.updateById(apArticle);

    }
}
